%%--- coding:utf-8 ---
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% File Name: mc_cursor
%%% Created on : 2024/5/2 21:28
%%% @author Gaylen 252323463@qq.com
%%% @copyright (C) 2024, freedom
%%% @doc
%%%
%%% @end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-module(mc_cursor).
-behaviour(gen_server).
-author("Gaylen").
-include("mongodb_driver.hrl").

%% Public API
-export([

]).

%% API
-export([
    start_link/5,
    init/1,
    close/1,
    handle_call/3,
    handle_cast/2,
    handle_info/2,
    terminate/2,
    code_change/3,
    next/2
]).

start_link(Connection, Database, Collection, CursorId, BatchSize) ->
    gen_server:start_link(?MODULE, [self(), Connection, Database, Collection, CursorId, BatchSize], []).

%% @hidden
init([Owner, Connection, Database, Collection, CursorId, BatchSize]) ->
    Monitor = erlang:monitor(process, Owner),
    {ok, #mongo_cursor_state{
        connection = Connection,
        database = Database,
        collection = Collection,
        cursor_id = CursorId,
        batch_size = BatchSize,
        monitor = Monitor
    }}.

-spec close(pid()) -> ok.
close(CursorPid) ->
    gen_server:cast(CursorPid, halt).

handle_call({next, BatchSize}, _From, State) ->
    #mongo_cursor_state{
        connection = Connection,
        database = Database,
        collection = Collection,
        cursor_id = CursorId,
        batch_size = BatchSize
    } = State,
    Result = mc_worker_api_logic:database_get_more(Connection, Database, Collection, CursorId, BatchSize),
    {reply, Result, State};
handle_call(_Request, _From, State) ->
    {reply, ok, State}.

%% @hidden
handle_cast(halt, State) ->
    {stop, normal, State};
handle_cast(_, State) ->
    {noreply, State}.

%% @hidden
handle_info({'DOWN', Monitor, process, _, _}, #mongo_cursor_state{monitor = Monitor} = State) ->
    {stop, normal, State};
handle_info(_, State) ->
    {noreply, State}.

%% @hidden
terminate(_, #mongo_cursor_state{cursor_id = 0}) ->
    ok;
terminate(_, State) ->
    %% 发起killCursor请求
    #mongo_cursor_state{
        connection = Connection,
        database = Database,
        collection = Table,
        cursor_id = CursorId
    } = State,
    mc_worker_api_logic:database_kill_cursor(Connection, Database, Table, CursorId),
    {ok, State#mongo_cursor_state{cursor_id = 0}}.

%% @hidden
code_change(_Old, State, _Extra) ->
    {ok, State}.

next(CursorPid, BatchSize) ->
    gen_server:call(CursorPid, {next, BatchSize}, mc_utils:get_timeout()).

